/* ***********************************************************************************
 * name: RTC_STM32.c
 * author:Duy Vinh
 *
 * description:
 * 	provide function to work with RTC module of STM32 MCU
 *
 * ***********************************************************************************
 */

//#include "CoOS.h"
#include "RTC_STM32.h"
#include "stm32f10x_rtc.h"
#include "stm32f10x_pwr.h"
#include "stm32f10x_bkp.h"
#include "stm32f10x.h"
//#include "AppConfig.h"

extern USART_TypeDef* USARTx;

#define RefYear  2000 // reference year
/*
 * *******************************************************
 * function check if year is a leap year
 *
 * return number of days in year
 * *******************************************************
 */
int CheckLeapYear(int year) {
	if (year % 4 == 0)
		return 366;
	else
		return 365;
}

/*
 * *******************************************************
 * function check month
 *
 * return number of days in month
 * *******************************************************
 */
int CheckMonth(int mon, int year) {
	int mon30[] = { 4, 6, 9, 11 };
	int pos = 0;
	if (mon == 2) {
		return (CheckLeapYear(year) - 337);//return 29 if leap year, 28 if not
	}
	while (1) {
		if (mon30[pos] == '\0')
			return 31;
		if (mon30[pos] == mon)
			return 30;
		pos++;
	}
}

/*
 * *******************************************************************
 * count number of seconds form start of year to this month
 *
 * return number of seconds (uint32_t)
 * *******************************************************************
 */
uint32_t SecCountToMonth(int mon, int year) {
	uint32_t sec = 0;
	int smon;
	for (smon = 1; smon < mon; smon++) {
		sec = sec + CheckMonth(smon, year) * 60 * 60 * 24;
	}
	return sec;
}

/*
 * *******************************************************************
 * count number of days form start of year to this month
 *
 * return number of days (uint32_t)
 * *******************************************************************
 */
uint32_t DayCountToMonth(int mon, int year) {
	uint32_t day = 0;
	int smon;
	for (smon = 1; smon < mon; smon++) {
		day = day + CheckMonth(smon, year);
	}
	return day;
}
/*
 * *******************************************************************
 * count number of seconds form referent year to this year
 *
 * return number of seconds (uint32_t)
 * *******************************************************************
 */
uint32_t SecCountToYear(int year) {
	uint32_t sec = 0;
	int syear;
	for (syear = RefYear; syear < year; syear++) {
		sec = sec + CheckLeapYear(syear) * 60 * 60 * 24;
	}
	return sec;
}

/*
 * *******************************************************************
 * count number of days form referent year to this year
 *
 * return number of days (uint32_t)
 * *******************************************************************
 */
uint32_t DayCountToYear(int year) {
	uint32_t day = 0;
	int syear;
	for (syear = RefYear; syear < year; syear++) {
		day = day + CheckLeapYear(syear);
	}
	return day;
}

/*
 * ********************************************************************
 * function setting count value for RTC module
 *
 * return none
 * ********************************************************************
 */
void SetRTCtime(DateTime date) {

	uint32_t value = 0;
	value = value + date.second;
	value = value + date.minute * 60;
	value = value + date.hour * 60 * 60;
	value = value + (date.day - 1) * 60 * 60 * 24;
	value = value + SecCountToMonth(date.month, date.year);
	value = value + SecCountToYear(date.year + 2000);

	PWR_BackupAccessCmd(ENABLE);
	RTC_WaitForLastTask();
	RTC_SetCounter(value);
	RTC_WaitForLastTask();
	PWR_BackupAccessCmd(DISABLE);
}

/*
 * ********************************************************************
 * function getting count value from RTC module
 *
 * return none
 * ********************************************************************
 */
void GetRTCtime(DateTime* date) {
	uint32_t sday;
	int tday, tmonth, tyear, thour, tminute, tsecond;

	RTC_WaitForLastTask();
	uint32_t value = RTC_GetCounter();

	tsecond = value % 60;
	tminute = (value / 60) % 60;
	thour = (value / (60 * 60)) % 24;
	tday = (value / (60 * 60 * 24));
	tmonth = 0;
	sday = 0;
	tyear = RefYear - 1;
	do {
		tyear++;
		sday = sday + CheckLeapYear(tyear);
	} while (sday <= tday);
	tday = tday - (sday - CheckLeapYear(tyear));
	sday = 0;
	tmonth = 0;
	do {
		tmonth++;
		sday = sday + CheckMonth(tmonth, tyear);
	} while (sday <= tday);
	tday = tday - (sday - CheckMonth(tmonth, tyear)) + 1;

	date->day = tday;
	date->month = tmonth;
	date->year = tyear;
	date->hour = thour;
	date->minute = tminute;
	date->second = tsecond;
}

